﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace Light.IoC
{
    public class DefaultFactory : IFactory
    {
        private static Dictionary<string, object> container = null;

        /// <summary>
        /// 构造函数，加载类实例
        /// </summary>
        public DefaultFactory()
        {
            InitContainer();
        }

        public T Create<T>()
        {
            string service = typeof(T).FullName + "," + typeof(T).Assembly.GetName().Name;
            string key = container.Keys.FirstOrDefault(t => t.StartsWith(service));

            if (!String.IsNullOrEmpty(key))
                return (T)container[key];
            else
                throw new Exception("无法加载接口 " + service + " 的实现类，请检查配置。");
        }

        public T Create<T>(string key)
        {
            key = typeof(T).FullName + "," + typeof(T).Assembly.GetName().Name + "_" + key;
            if (container.ContainsKey(key))
                return (T)container[key];
            else
                throw new Exception("无法加载组件ID " + key + " 的实现类，请检查配置。");
        }

        public object Create(Type type)
        {
            string service = type.Assembly.FullName + "," + type.FullName;
            string key = container.Keys.FirstOrDefault(t => t.StartsWith(service));

            if (!String.IsNullOrEmpty(key))
                return container[key];
            else
                throw new Exception("无法加载接口 " + service + " 的实现类，请检查配置。");
        }

        public void Dispose()
        {
            container = null;
        }

        /// <summary>
        /// 初始化容器
        /// </summary>
        private void InitContainer()
        {
            if (container == null)
            {
                lock (this)
                {
                    container = new Dictionary<string, object>();

                    string componentPath = Light.Utility.ApplicationSetting.ReadAppSetting("component.path", "");
                    if (String.IsNullOrEmpty(componentPath))
                        throw new Exception("appSettings中不包含名称为 component.path 的节点，IOC组件初始化失败。");

                    string filePath = Light.Utility.WebHelper.GetRootPath() + componentPath;

                    if (!File.Exists(filePath))
                        throw new Exception(filePath + "，文件不存在。");

                    XDocument document = XDocument.Load(filePath);
                    var components = document.Element("configuration").Element("components").Elements("component");
                    foreach (var component in components)
                    {
                        string id = component.Attribute("id").Value;
                        string service = component.Attribute("service").Value;
                        string[] type = component.Attribute("type").Value.Split(',');

                        string typeClassName = type[0];
                        string typeAssemblyName = type[1];

                        Assembly typeAssembly = Assembly.Load(typeAssemblyName);

                        object instance = typeAssembly.CreateInstance(typeClassName);

                        string key = service + "_" + id;
                        if (!container.ContainsKey(key))
                            container.Add(key, instance);
                    }
                }
            }
        }

    }
}
